﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Surging.Base.SwaggerBuilders;
using Surging.Core.CPlatform;
using Surging.Core.CPlatform.Ioc;
using Surging.Core.CPlatform.Runtime.Server.Implementation.ServiceDiscovery.Attributes;
using Surging.Core.ServiceHosting.Internal;

namespace Surging.Base
{
    public static class SwaggerBuilder
    {

        public static IServiceHostBuilder RegisterSwaggers(this IServiceHostBuilder builder, params string[] virtualPaths)
        {
            var jsonstr = new Dictionary<string, object>();
            var definitions = new Dictionary<string, object>();
            try
            {
                var referenceAssemblies = ReflectionHelpers.GetReferenceAssembly(virtualPaths);
                foreach (var assembly in referenceAssemblies)
                {
                    foreach (var type in assembly.GetTypes().Where(t =>
                        typeof(ServiceBase).GetTypeInfo().IsAssignableFrom(t) &&
                        t.GetTypeInfo().GetCustomAttribute<ModuleNameAttribute>() != null))
                    {

                        var interfaceObj = type.GetInterfaces()
                            .FirstOrDefault(t => typeof(IServiceKey).GetTypeInfo().IsAssignableFrom(t));
                        if (interfaceObj != null && interfaceObj.GetCustomAttribute<ServiceBundleAttribute>() != null)
                        {
                            var typerootname = type.Name.Replace("Service", "");
                            var rootpath = "/api/" + typerootname + "/";
                            interfaceObj.GetMethods().ToList().ForEach(x =>
                            {
                                var dto = ReflectionHelpers.GetReturnType(x);
                                definitions = ReflectionHelpers.GetParameterTypes(definitions, dto, x.GetParameters());
                                var input = x.GetParameters().Select(y => new ParameterDto
                                {
                                    name = y.Name,
                                    @in = "body",
                                    required = false,
                                    schema = new
                                    {
                                        refs = "#/definitions/" + y.ParameterType.Name
                                    }
                                }).ToList();
                                input.Add(new ParameterDto
                                {
                                    name = "Authorization",
                                    @in = "header", //query header body path formData  
                                    type = "string",
                                    required = false //是否必选  
                                });
                                jsonstr.Add(rootpath + x.Name, new
                                {
                                    post = new
                                    {
                                        tags = new List<string>() {typerootname},
                                        operationId = $"Api{typerootname}{x.Name}Post",
                                        consumes = new List<string>()
                                        {
                                            "application/json-patch+json",
                                            "application/json",
                                            "text/json",
                                            "application/*+json"
                                        },
                                        produces = new List<string>()
                                        {
                                            "text/plain",
                                            "application/json",
                                            "text/json"
                                        },
                                        parameters = input,
                                        responses = new
                                        {
                                            OK = new
                                            {
                                                description = "Success",
                                                schema = new
                                                {
                                                    refs = "#/definitions/" + dto.Name
                                                }
                                            }
                                        }
                                    }
                                });
                            });
                        }

                    }
                }
                var result =
                    JsonConvert.SerializeObject(new { definitions , paths=jsonstr }).Replace("OK", "200").Replace("refs", "$ref").Replace("inbody", "in");
                if (!Directory.Exists(Directory.GetCurrentDirectory() + "/swagger/"))
                {
                    Directory.CreateDirectory(Directory.GetCurrentDirectory() + "/swagger/");
                }
                File.WriteAllText(Directory.GetCurrentDirectory() + "/swagger/swagger.json", result);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return builder;
        }


    }
}
